package com.chen.config;

import com.chen.filter.ValidCodeFilter;
import com.chen.service.UserInfoServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class SecurityConfig implements WebMvcConfigurer {
    @Autowired
    ValidCodeFilter validCodeFilter;

    @Autowired
    UserInfoServiceImpl userInfoService;
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
        //如果不想加密就返回
//        return NoOpPasswordEncoder.getInstance();
    }


//    @Bean
//    public UserDetailsService userDetailsService() {
//        // 1.使用内存数据进行认证
//        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
//        // 2.创建4个用户
//        ////设置内存用户名与密码,并赋与角色
//        UserDetails user1 = User.withUsername("admin").password(passwordEncoder().encode("123")).roles("role1","role2","role3").build();
//        UserDetails user2 = User.withUsername("user1").password(passwordEncoder().encode("123")).roles("role1").build();
//        UserDetails user3 = User.withUsername("user2").password(passwordEncoder().encode("123")).roles("role2").build();
//        UserDetails user4 = User.withUsername("user3").password(passwordEncoder().encode("123")).roles("role3").build();
//
//        // 3.将这4个用户添加到内存中
//        manager.createUser(user1);
//        manager.createUser(user2);
//        manager.createUser(user3);
//        manager.createUser(user4);
//        return manager;
//    }

    //静态资源直接放行
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        //忽略这些静态资源（不拦截）  新版本 Spring Security 6.0 已经弃用 antMatchers()
        return (web) -> web.ignoring().requestMatchers("/js/**", "/css/**","/images/**","/webjars/**");
    }

    @Bean
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.addFilterBefore(validCodeFilter, UsernamePasswordAuthenticationFilter.class);
        httpSecurity.authorizeRequests() //开启登录配置
                .requestMatchers("/","/validcode").permitAll() //允许直接访问的路径,包括验证码
                .requestMatchers("/level1/**").hasRole("vip1")
                .requestMatchers("/level2/**").hasRole("vip2")
                .requestMatchers("/level3/**").hasRole("vip3")
                .anyRequest().authenticated();//其他任何请求都必须经过身份验证
        httpSecurity.formLogin()//开启表单验证
                .loginPage("/toLogin")//跳转到自定义的登录页面
                .usernameParameter("username")//自定义表单的用户名的name,默认为username
                .passwordParameter("password")//自定义表单的密码的name,默认为password
                .loginProcessingUrl("/login")//表单请求的地址，使用Security定义好的/login，并且与自定义表单的action一致
                .failureUrl("/toLogin/error")//如果登录失败跳转到
                .permitAll();//允许访问登录有关的路径//开启表单验证

        //开启注销
        httpSecurity.rememberMe(); //记住我
        httpSecurity.logout().logoutSuccessUrl("/");//注销后跳转到index页面
        httpSecurity.csrf().disable();//关闭csrf
        httpSecurity.exceptionHandling().accessDeniedPage("/errorRole");
        httpSecurity.userDetailsService(userInfoService);//代替内存写死的用户
           return httpSecurity.build();
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/errorRole").setViewName("errorRole");
    }
}

